//
//  SortableController.swift
//
//  Created by 谢强 on 15/03/2018.
//  Copyright © 2018 谢强. All rights reserved.
//

import UIKit

/// 排序状态
enum SortState {
    // 初始状态
    case ready(snapshotRow: IndexPath?)
    // 正在排序
    case updating(context: SortContext)
}
/// 携带的数据
struct SortContext {
    var sourceRow: IndexPath
    var destinationRow: IndexPath
    var snapshotOffset: CGFloat
    var touchPosition: CGPoint
}

public class SortableController: NSObject {
    
    // MARK: - Delegate
    public weak var delegate: JWSortableTableViewDelegate?
    
    // MARK: - Config
    /// The duration of the cell selection animation.
    public var animationDuration: TimeInterval = 0.2
    
    /// The transparent of the selected cell.
    public var cellTransparent: Bool = false
    
    /// The opacity of the selected cell.
    public var cellOpacity: CGFloat = 1
    
    /// The scale factor for the selected cell.
    public var cellScale: CGFloat = 1
    
    /// The shadow color for the selected cell.
    public var shadowColor: UIColor = .black
    
    /// The shadow opacity for the selected cell.
    public var shadowOpacity: CGFloat = 0.3
    
    /// The shadow radius for the selected cell.
    public var shadowRadius: CGFloat = 4
    
    /// The shadow offset for the selected cell.
    public var shadowOffset = CGSize(width: 0, height: 2)
    
    /// Whether auto scroll is enable.
    public var autoScroll_enable = true
    
    /// Whether reordering is enabled.
    public var isReorderEnable: Bool = true {
        didSet {
            longPressGesture.isEnabled = isReorderEnable
        }
    }
    
    // MARK: - Property - Normal
    weak var tableView: UITableView?
    
    var snapshotView: UIView? = nil
    
    var sortState: SortState = .ready(snapshotRow: nil)
    
    // MARK: - Property - AutoScroll
    var autoScroll_displayLink: CADisplayLink?
    var autoScroll_lastTImeStap: CFTimeInterval?
    
    // MARK: - Property - Lazy
    lazy var longPressGesture: UILongPressGestureRecognizer = {
        let gesture = UILongPressGestureRecognizer(target: self, action: #selector(handleLongPressGesture(gesture:)))
        gesture.delegate = self
        return gesture
    }()

    // MARK: - 构造函数
    init(tableview: UITableView) {
        super.init();
        
        tableview.addGestureRecognizer(longPressGesture)
        self.tableView = tableview
        
        sortState = SortState.ready(snapshotRow: nil)
    }
    
    
}

// MARK: - 执行函数
extension SortableController {
    
    /// 开始
    func beginReorder(startPoint pointInSuperview: CGPoint) {
        // 校验
        guard
            case SortState.ready = sortState,
            let delegate = delegate,
            let tableView = tableView,
            let superview = tableView.superview
        else { return }
        
//        if 0...9 ~= 3 {
//            print(3)
//        }
        
        // 开始
        let pointInTableView = superview.convert(pointInSuperview, to: tableView)
        
        guard
            let sourceRow = tableView.indexPathForRow(at: pointInTableView),
            delegate.jw_tableView(tableView, isSortableAt: sourceRow)
        else { return }
        
        snapshot_createFromCell(at: sourceRow)
        snapshot_animateIn()
        autoScroll_active()
        
        tableView.reloadData()
        
        let snapshotOffset = (snapshotView?.center.y ?? 0) - pointInSuperview.y
        
        let context = SortContext(
            sourceRow: sourceRow,
            destinationRow: sourceRow,
            snapshotOffset: snapshotOffset,
            touchPosition: pointInSuperview
        )
        sortState = SortState.updating(context: context)
        
        delegate.jw_tableViewSortBegin(tableView, from: sourceRow)
    }
    
    /// 更新
    func updateReorder(changedPoint: CGPoint) {
        // 校验
        guard case SortState.updating(let context) = sortState else { return }
        
        var newContext = context
        newContext.touchPosition = changedPoint
        sortState = SortState.updating(context: newContext)
        
        snapshot_updatePosition()
        destinationRow_update()
    }
    
    /// 停止
    func endReorder() {
        // 校验
        guard
            case let SortState.updating(context) = sortState,
            let tableView = tableView,
            let superview = tableView.superview
        else { return }
        
        sortState = SortState.ready(snapshotRow: context.destinationRow)
        
        let cellRectInTableView = tableView.rectForRow(at: context.destinationRow)
        let cellRect = tableView.convert(cellRectInTableView, to: superview)
        let cellRectCenter = CGPoint(x: cellRect.midX, y: cellRect.midY)
        
        if snapshotView?.center == cellRectCenter {
            snapshotView?.center.y += 0.1
        }
        
        UIView.animate(withDuration: animationDuration, animations: {
            self.snapshotView?.center = cellRectCenter
        }) { (_) in
            if case SortState.ready(let snapshotRow) = self.sortState, let row = snapshotRow {
                self.sortState = SortState.ready(snapshotRow: nil)
                UIView.performWithoutAnimation {
                    tableView.reloadRows(at: [row], with: .none)
                }
                self.snapshot_remove()
            }
        }
        
        snapshot_animateOut()
        autoScroll_clear()
        
        delegate?.jw_tableViewSortEnd(tableView, destination: context.destinationRow)
    }
}

// MARK: - Public
extension SortableController {
    
    public func emptyCell(indexPath: IndexPath) -> UITableViewCell? {
        if case SortState.ready(let snapshotRow) = sortState, indexPath == snapshotRow {
            return createEmptyCell()
        } else if case SortState.updating(let context) = sortState, case indexPath = context.destinationRow {
            return createEmptyCell()
        }
        return nil
    }
    
    private func createEmptyCell() -> UITableViewCell? {
        guard let _ = snapshotView, let tableView = tableView else { return nil }
        
        if let cell = delegate?.jw_tableViewEmptyCell(tableView) {
            return cell
        } else {
            let cell = UITableViewCell()
            cell.backgroundColor = UIColor.clear
            return cell
        }
    }
}
